package com.alibaba.nacos.config.server.jpa.aspect;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import com.alibaba.nacos.config.server.jpa.service.IPersistService;
import com.alibaba.nacos.config.server.jpa.service.impl.PersisitServiceHandlerImpl;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * The type of nacos-all.
 *
 * @author 问道于盲
 * @date 2020-03-10
 */
@Component
@Aspect
public class PersistServiceAspect {

    private static final Map<MethodInfo,Method> MAP = new HashMap<>();

    @Autowired
    private IPersistService persistService;

    static {
        Method[] declaredMethods = PersisitServiceHandlerImpl.class.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            String methodName = declaredMethod.getName();
            MethodInfo methodInfo = new MethodInfo(methodName, parameterTypes);
            MAP.put(methodInfo, declaredMethod);
        }
    }

    @Pointcut("within(com.alibaba.nacos.config.server.service.PersistService)")
    public void pointCut() {

    }

    @Around("pointCut()")
    public Object proceed(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Class[] parameterTypes = signature.getParameterTypes();
        Object[] args = joinPoint.getArgs();
        Method method = signature.getMethod();

        String methodName = method.getName();

        MethodInfo methodInfo = new MethodInfo(methodName, parameterTypes);

        Method targetMethod = MAP.get(methodInfo);

        if (Objects.nonNull(targetMethod)) {
            return targetMethod.invoke(persistService, args);
        }

        return joinPoint.proceed();

    }


}
